package com.zxjbyte.yiyi.module.system.manager;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zxjbyte.yiyi.framework.common.util.AuthUtil;
import com.zxjbyte.yiyi.framework.common.util.CollXUtil;
import com.zxjbyte.yiyi.framework.common.util.JsonUtil;
import com.zxjbyte.yiyi.module.system.domain.entity.DictItemPO;
import com.zxjbyte.yiyi.module.system.domain.entity.DictPO;
import com.zxjbyte.yiyi.module.system.domain.param.dict.DictItemAddParam;
import com.zxjbyte.yiyi.module.system.domain.param.dict.DictItemUpdateParam;
import com.zxjbyte.yiyi.module.system.enums.DictTypeEnum;
import com.zxjbyte.yiyi.module.system.service.DictItemService;
import com.zxjbyte.yiyi.module.system.service.DictService;
import com.zxjbyte.yiyi.module.system.util.cache.DictCacheUtil;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.zxjbyte.yiyi.framework.common.util.ValidationUtil.*;

/**
 * 字典管理器
 *
 * @Author zhangxingjia
 * @Date 2024/2/23 17:59
 * @Version: 1.0
 */
@Component
public class DictManager {

    private static DictManager instance;
    @Resource
    private DictItemService dictItemService;
    @Resource
    private DictService dictService;

    /**
     * 根据字典Code获取字典项 转成JSON字符串
     * @param dictCode 字典Code
     * @return
     */
    public String getDictItemAsJsonString(String dictCode){
        DictPO dictPo = dictService.lambdaQuery().select(DictPO::getId, DictPO::getDictCode).eq(DictPO::getDictCode, dictCode).one();
        if(dictPo != null){
            List<DictItemPO> list = dictItemService.listByDictId(dictPo.getId());
            if(CollXUtil.isNotEmpty(list)){
                return JsonUtil.toJsonAsString(list);
            }
        }
        return null;
    }

    /**
     * 删除字典项目
     * @param id
     */
    public void deleteDictItem(Long id) {
        DictItemPO dictItemPo = dictItemService.getById(id);
        assertNotNull(dictItemPo, () -> "字典项不存在");
        DictPO dictPo = checkDict(dictItemPo.getDictId());
        assertFalse(Objects.equals(dictPo.getType(), DictTypeEnum.SYSTEM_DICT.getCode()), "不可删除系统内置字典项");
        dictItemService.removeById(id);
        // 更新缓存
        initDictDateCache(dictPo.getId(), dictPo.getDictCode());
    }

    /**
     * 字段数据新增
     * @param request
     */
    public void saveDictItem(DictItemAddParam request) {
        assertNotNull(request.getDictId(), () -> "字典ID不可为空！");
        DictPO dictPo = checkDict(request.getDictId());
        DictItemPO entity = new DictItemPO();
        entity.setDictId(request.getDictId());
        entity.setSort(request.getSort());
        entity.setItemLabel(request.getItemLabel());
        entity.setItemValue(request.getItemValue());
        entity.setCssClass(request.getCssClass());
        entity.setStyleJson(request.getStyleJson());
        entity.setStatus(request.getStatus());
        entity.setRemark(request.getRemark());
        Date now = new Date();
        String username = AuthUtil.getUserName();
        entity.setCreateTime(now);
        entity.setCreateUser(username);
        entity.setUpdateTime(now);
        entity.setUpdateUser(username);
        dictItemService.save(entity);
        // 新增缓存
        initDictDateCache(dictPo.getId(), dictPo.getDictCode());
    }

    /**
     * 字典项编辑
     * @param request
     */
    public void updateDictItem(DictItemUpdateParam request){
        DictItemPO entity = dictItemService.getById(request.getId());
        assertFalse(Objects.isNull(entity), "字典项不存在！");
        // 字典项编辑，字典ID不可更改，前端置灰处理
        DictPO dictPo = checkDict(entity.getDictId());
        dictItemService.lambdaUpdate()
                .set(DictItemPO::getItemLabel, request.getItemLabel())
                .set(DictItemPO::getItemValue, request.getItemValue())
                .set(DictItemPO::getSort, request.getSort())
                .set(DictItemPO::getCssClass, request.getCssClass())
                .set(DictItemPO::getStyleJson, request.getStyleJson())
                .set(DictItemPO::getStatus, request.getStatus())
                .set(DictItemPO::getRemark, StrUtil.nullToEmpty(request.getRemark()))
                .set(DictItemPO::getUpdateUser, AuthUtil.getUserName())
                .set(DictItemPO::getUpdateTime, new Date())
                .eq(DictItemPO::getId, request.getId()).update();
        // 更新缓存
        initDictDateCache(dictPo.getId(), dictPo.getDictCode());
    }


    /**
     * 字典删除
     *
     * @param id
     */
    public void deleteDict(Long id) {
        DictPO dictPo = checkDict(id);
        assertFalse(Objects.equals(dictPo.getType(), DictTypeEnum.SYSTEM_DICT.getCode()), "不可删除系统内置字典");
        assertFalse(dictItemService.exists(Wrappers.<DictItemPO>lambdaQuery().eq(DictItemPO::getDictId, id)), "当前字典存在字典项，不可删除！");
        dictService.removeById(id);
        DictCacheUtil.removeDict(dictPo.getDictCode());
    }

    /**
     * 验证字典类型
     *
     * @param dictId 字典ID
     * @return
     */
    private DictPO checkDict(Long dictId){
        DictPO dictPo = dictService.getById(dictId);
        assertNotNull(dictPo, () -> "字典不存在！");
        return dictPo;
    }

    /**
     * 查询初始化字典数据缓存
     * @param dictId   字典id
     * @param dictCode  字典code
     */
    private void initDictDateCache(Long dictId, String dictCode){
        DictCacheUtil.setDict(dictCode, dictItemService.listByDictId(dictId));
    }

    @PostConstruct
    public void init() {
        instance = this;
    }

    public static DictManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException("DictManager not initialized yet");
        }
        return instance;
    }
}
